package io.github.consoles.dsa;

/**
 * Created by yiihua-013 on 17/6/11.
 * <p>
 * 环形缓冲区,又称为环形队列,是一种定长为N的FIFO
 * <p>
 * 在进程间的异步数据传输或者记录日志文件的时候非常有用
 * <p>
 * 缓冲区空:消费者等待
 * 缓冲区满:生产者等待
 * <p>
 * 环形缓冲区有固定的一块内存区域供生产者和消费者使用,节省了分配和释放内存的时间开销
 * <p>
 * 环形队列的关键是判断队列空和满。此处采用预留一个空闲运算的方法进行判断
 * <p>
 * 空:head == tail
 * 满:tail + 1 % cap = head
 */
public class RingBuffer<Item> {

    private          Item[] data;
    /**
     * 保证内存可见性
     */
    private volatile int    start;
    private volatile int    end;

    private static final int DEFAULT_CAP = 4;

    public RingBuffer(int cap) {
        data = (Item[]) new Object[cap];
    }

    public RingBuffer() {
        this(DEFAULT_CAP);
    }

    boolean isFull() {
        return (end + 1) % data.length == start;
    }

    boolean isEmpty() {
        return start == end;
    }

    boolean write(Item item) {
        if (isFull()) return false;

        data[end] = item;
        end = (end + 1) % data.length;
        return true;
    }

    Item read() {
        if (isEmpty()) return null;
        Item item = data[start];
        start = (start + 1) % data.length;
        return item;
    }
}
